#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include<openssl/md5.h>
#include<string.h>
#include <time.h>

#define ROOT_DEBUG

char* host = "appservice.lenovomm.com";
int port = 80;
#define API_KEY  "rootbackup"
#define AP_ISECRET "548a3d7f383d6f60df312eefc6bb21b4"

#define MAX_STR_LENGTH  50
#define SLEEP_TIME_SECOND  30
#define MAX_MESSAGE_LENGTH 2048
#define MAX_MD5_LEN 33
#define ROOT_TEST

/*
 *  http://appservice.lenovomm.com/lenovo-bless/common/root/backup?imei=123457&version=1.1.15&kernelversion=1
 *  GET /lenovo-bless/common/root/backup?imei=123457&version=1.1.15&kernelversion=1 HTTP/1.1
 */
//GET /lenovo-bless/common/root/backup?imei=123457&version=1.1.15&kernelversion=1 HTTP/1.1
//Host: appservice.lenovomm.com
//User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0
//Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
//Accept-Language: zh-cn,en-us;q=0.8,zh;q=0.5,en;q=0.3
//Accept-Encoding: gzip, deflate
//DNT: 1
//Cookie: LenovoID.UN=491804300@qq.com; LPSState=1
//Connection: keep-alive
//
//HTTP/1.1 200 OK
//Server: nginx/1.5.2
//Date: Wed, 13 Nov 2013 07:49:45 GMT
//Content-Type: application/json;charset=utf-8
//Content-Length: 20
//Connection: Keep-Alive
//
//{"ret":0,"msg":"ok"}
static int process_status_code(char * msg);
static int md5string(unsigned char *data, int length, unsigned char *out,
		int outlength);
static void getbasebandversion(char *str, int len);
static void getimei(char *str, int len);
static void getkernelversion(char *str, int len);
static void getlesafeexist(char *str, int len);
static void getroot(char *str, int len);
static void gettimestamp(char *str,int len);
static void getuser(char *str, int len);
static void getversion(char *str, int len);
int main(void) {
	char buffer[MAX_MESSAGE_LENGTH];
	char buffer_for_sign[MAX_MESSAGE_LENGTH];
	char md5value[MAX_MD5_LEN] ={'\0'};
	int isock;
	struct sockaddr_in pin;
	struct hostent * remoteHost;
	char message[MAX_MESSAGE_LENGTH];
	int done = 0;
	int chars = 0;
	int l = 0;
	int receivecount =0;

	char receivemsg[1024];
	char myimei[20]={0};
	char myversion[50]={0};
	char mykernelversion[50]={0};

	char basebandversion[MAX_STR_LENGTH] = {'\0'};
	char imei[MAX_STR_LENGTH] = {'\0'};
	char kernelversion[MAX_STR_LENGTH] = {'\0'};
	char lesafeexist[MAX_STR_LENGTH] = {'\0'};
	char root[MAX_STR_LENGTH] = {'\0'};
	char timestamp[MAX_STR_LENGTH] = {'\0'};
	char user[MAX_STR_LENGTH] = {'\0'};
	char version[MAX_STR_LENGTH] = {'\0'};

	int status_code = 0;

	getbasebandversion(basebandversion,sizeof(basebandversion));
	getimei(imei,sizeof(imei));
	getkernelversion(kernelversion,sizeof(kernelversion));
	getlesafeexist(lesafeexist,sizeof(lesafeexist));
	getroot(root,sizeof(root));
	gettimestamp(timestamp,sizeof(timestamp));
	getuser(user,sizeof(user));
	getversion(version,sizeof(version));
	/*
	"basebandversion", =>""  , "imei" => "12345678" , "kernelversion" => "" ,
	 "lesafeexist" => "" , "root" => ""，“timestamp”=>"1384410807730 " ,  "user" => "" , "version" => ""
	 */
	snprintf(buffer,
			sizeof(buffer)-32,
			//"basebandversion=%s&imei=%s&kernelversion=%s&lesafeexist=%s&root=%s&timestamp=%s&user=%s&version=%s",
			"basebandversion=%s&imei=%s&kernelversion=%s&lesafeexist=%s&root=%s&user=%s&version=%s",
			basebandversion,
			imei,
			kernelversion,
			lesafeexist,
			root,
			//timestamp,
			user,
			version
			);
#ifdef ROOT_DEBUG
	printf("buffer=%s\n",buffer);
#endif
	strcat(buffer_for_sign,buffer);
	strcat(buffer_for_sign,AP_ISECRET);
	printf("buffer ready for sign=%s\n",buffer_for_sign);
	md5string(buffer_for_sign,strlen(buffer_for_sign),md5value,sizeof(md5value));
	strcat(buffer,"&apikey=rootbackup");
	strcat(buffer,"&sign=");
	strcat(buffer,md5value);
#ifdef ROOT_DEBUG
	printf("after md5 buffer=%s\n",buffer);
#endif
	sprintf(message, "GET /lenovo-bless/common/root/backup?%s HTTP/1.1\n",buffer);
	strcat(message, "Host:appservice.lenovomm.com\r\n");
	//strcat(message, "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n");
	//strcat(message, "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0\r\n");
	strcat(message, "connection:keep-alive\r\n");
	//strcat(message,"Cookie: LenovoID.UN=491804300@qq.com; LPSState=1\r\n");
	strcat(message, "\r\n\r\n");

	printf("http head:%s\n", message);
	while (1) {
		if ((remoteHost = gethostbyname(host)) == NULL) {
				printf("Error resolving host\n");
#ifdef ROOT_TEST
				exit(0);
#endif
				sleep(SLEEP_TIME_SECOND);
			}
		#ifdef ROOT_DEBUG
			printf("remoteHost:%s\n",remoteHost->h_name);
		#endif
			bzero(&pin, sizeof(pin));
			pin.sin_family = AF_INET;
			pin.sin_port = htons(port);
			pin.sin_addr.s_addr = ((struct in_addr *) (remoteHost->h_addr) )->s_addr;

			if ((isock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
				printf("Error opening socket!\n");
#ifdef ROOT_TEST
				exit(0);
#endif
				sleep(SLEEP_TIME_SECOND);
			}
		if (connect(isock, (void *) &pin, sizeof(pin)) == -1) {
			printf("Error connecting to socket\n");
#ifdef ROOT_TEST
				exit(0);
#endif
			sleep(SLEEP_TIME_SECOND);
		}

		if (send(isock, message, strlen(message), 0) == -1) {
			printf("Error in send\n");
#ifdef ROOT_TEST
				exit(0);
#endif
			sleep(SLEEP_TIME_SECOND);
		}

		receivecount = recv(isock, receivemsg, 1024, 0);
		if (receivecount != 0) {
#ifdef ROOT_DEBUG
			printf("return message:%s\n", receivemsg);
#endif
			status_code = process_status_code(receivemsg);
			printf("receive status_code:%d\n", status_code);

			switch (status_code) {
			case 200:
				printf("everything goes well,i will exit\n");
				exit(0);
				break;
			default:
				sleep(SLEEP_TIME_SECOND);
				break;
			}
		} else {
			printf("receive error\n");
			sleep(SLEEP_TIME_SECOND);
		}
	}
	close(isock);
	return 0;
}


static int process_status_code(char * msg)
{
	int i,j;
	char num[50];

	for(i = 0; msg[i] != ' '; i++);
	i++;
	for(j = 0; msg[i] != ' '; i++,j++)
		num[j] = msg[i];
	num[j] = '\0';

	return  atoi(num);
}

static int md5string(unsigned char *data, int length, unsigned char *out,
		int outlength) {
	unsigned char md[16];
	int i;
	char tmp[3] = { '\0' }, buf[33] = { '\0' };
	MD5(data, strlen(data), md);
	for (i = 0; i < 16; i++) {
		sprintf(tmp, "%2.2x", md[i]);
		strcat(buf, tmp);
	}
	printf("%s\n", buf);
	strncpy(out, buf, outlength);
	return 0;
}

/*
char basebandversion[MAX_STR_LENGTH] = {'\0'};
	char imei[MAX_STR_LENGTH] = {'\0'};
	char kernelversion[MAX_STR_LENGTH] = {'\0'};
	char lesafeexist[MAX_STR_LENGTH] = {'\0'};
	char root[MAX_STR_LENGTH] = {'\0'};
	char timestamp[MAX_STR_LENGTH] = {'\0'};
	char user[MAX_STR_LENGTH] = {'\0'};
	char version[MAX_STR_LENGTH] = {'\0'};
	*/

static void getbasebandversion(char *str, int len){
	if (NULL == str || 0 == len){
		return;
	}
#ifdef ROOT_TEST
	snprintf(str,len,"%s","basebandversion");
#endif
	return;
}
static void getimei(char *str, int len){
	if (NULL == str || 0 == len){
		return;
	}
#ifdef ROOT_TEST
	snprintf(str,len,"%s","imei");
#endif
	return;
}
static void getkernelversion(char *str, int len){
	if (NULL == str || 0 == len){
		return;
	}
#ifdef ROOT_TEST
	snprintf(str,len,"%s","getkernelversion");
#endif
	return;
}
static void getlesafeexist(char *str, int len){
	if (NULL == str || 0 == len){
		return;
	}
#ifdef ROOT_TEST
	snprintf(str,len,"%s","getlesafeexist");
#endif
	return;
}
static void getroot(char *str, int len){
	if (NULL == str || 0 == len){
		return;
	}
#ifdef ROOT_TEST
	snprintf(str,len,"%s","getroot");
#endif
	return;
}
static void gettimestamp(char *str,int len){
	time_t t;
	struct timeval tp;
	if (NULL == str || 0 == len){
			return;
	}
    //t = time(0);

	gettimeofday(&tp,NULL);
    printf("time_t: %d\n",tp.tv_sec);
    snprintf(str,len,"%lld",t);
#ifdef ROOT_DEBUG
    printf ("time stamp:%s\n",str);
#endif
    return;
}
static void getuser(char *str, int len){
	if (NULL == str || 0 == len){
		return;
	}
#ifdef ROOT_TEST
	snprintf(str,len,"%s","getuser");
#endif
	return;
}
static void getversion(char *str, int len){
	if (NULL == str || 0 == len){
		return;
	}
#ifdef ROOT_TEST
	snprintf(str,len,"%s","getversion");
#endif
	return;
}

